﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using PrgsMgr.CStructure;
using System.Runtime.InteropServices;
namespace PrgsMgr
{
    /// <summary>
    /// 进度信息类
    /// </summary>
    public class ProgressInfo
    {
        /// <summary>
        /// 线程ID
        /// 每一个线程对应一个进度信息，每次更新都是通过线程ID区别
        /// </summary>
        public int ThdId { get; set; }
        /// <summary>
        /// 进度当前值，百分比
        /// </summary>
        public float CurrentVal { get; set; }
        /// <summary>
        /// 进度当前位置
        /// </summary>
        public long CurrentPos { get; set; }
        /// <summary>
        /// 进度最大值
        /// </summary>
        public long MaxPos { get; set; }
        /// <summary>
        /// 进度条状态
        /// </summary>
        public string Status { get; set; }
        /// <summary>
        /// 进度附加状态
        /// </summary>
        public string ExStatus { get; set; }
    }


    /// <summary>
    /// 进度条管理类
    /// 每一个线程都有一个进度条显示，通过线程ID区别
    /// </summary>
    public static class ProgressManager
    {
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref  CStructure.PROGRESS_INFO lParam);
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
        /// <summary>
        /// 存储每一个线程的ID队列
        /// </summary>
        private static List<ProgressInfo> LstProgress = new List<ProgressInfo>();
        public static void SetHwnd(IntPtr Hwnd)
        {
            PubVal.ProcessHwnd = Hwnd;
        }
        /// <summary>
        /// 更新进度
        /// </summary>
        /// <param name="thdId">线程ID</param>
        /// <param name="val">更新值</param>
        public static void UpdateVale(int thdId, long val = 1)
        {
            ProgressInfo Info = GetProgressInfo(thdId);
            Info.CurrentPos += val;
            UpdateProgress(Info);
        }
        public static void UpdateVale(int thdId, string str,bool bMsg = false)
        {
            ProgressInfo Info = GetProgressInfo(thdId);
            Info.Status = str;
            PROGRESS_INFO progressInfo = new PROGRESS_INFO();
            progressInfo.Status = "状态：" + str;
            progressInfo.ProgressVisible = false;
            progressInfo.bMsg = bMsg;
            SendMessage(PubVal.ProcessHwnd, (int)WM_MSG.WM_MSG_PROCESS_UPDATE, IntPtr.Zero, ref progressInfo);
        }
        /// <summary>
        /// 设置附加状态
        /// </summary>
        /// <param name="thdId">进度条ID</param>
        /// <param name="str">附加状态</param>
        public static void SetExStatus(int thdId, string str)
        {
            ProgressInfo info;
            if (!IdExists(thdId))
            {
                info = AddProgressInfo(thdId);
            }
            else
            {
                info = GetProgressInfo(thdId);
            }
            info.ExStatus = str;
        }
        /// <summary>
        /// 进度条初始化
        /// </summary>
        /// <param name="htdId">线程ID</param>
        /// <param name="status">进度显示状态</param>
        /// <param name="max">进度条最大值</param>
        /// <param name="pos">进度条初始值</param>
        public static void Init( int htdId,string status,long max,long pos = 0)
        {
            ProgressInfo info;
            //判断当前线程ID的进度信息是否存在，如果不存在则添加新的
            if (!IdExists(htdId))
            {
                info = AddProgressInfo(htdId);
            }
            else
            {
                info = GetProgressInfo(htdId);
            }
            //初始化进度信息
            info.Status = status;
            info.MaxPos = max;
            info.CurrentVal = 0;
            info.CurrentPos = 0;
            UpdateStringInfo(status);
        }
        /// <summary>
        /// 进度条初始化
        /// 在处理过程最开始时调用次初始化，清除所有进度信息
        /// </summary>
        public static void Init()
        {

            if (LstProgress != null)
            {
                LstProgress.Clear();
            }
            else
            {
                LstProgress = new List<ProgressInfo>();
            }
        }
        /// <summary>
        /// 判断当前线程进度条信息是否存在
        /// </summary>
        /// <param name="thdId">进度条ID</param>
        /// <returns>true 进度条信息存在</returns>
        private static bool IdExists(int thdId)
        {
            //循环判断是否存在进度信息
            foreach (var info in LstProgress)
            {
                if (info.ThdId == thdId)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 返回特定ID的进度条信息
        /// </summary>
        /// <param name="thdId">线程进度ID</param>
        /// <returns>进度信息</returns>
        private static ProgressInfo GetProgressInfo(int thdId)
        {
            foreach (var info in LstProgress)
            {
                if (info.ThdId == thdId)
                {
                    return info;
                }
            }
            return null;
        }
        /// <summary>
        /// 添加初始化进度信息
        /// </summary>
        /// <param name="thdId">线程进度ID</param>
        /// <returns>添加后的进度信息</returns>
        private static ProgressInfo AddProgressInfo(int thdId)
        {
            ProgressInfo info = new ProgressInfo();
            info.ThdId = thdId;
            LstProgress.Add(info);
            return info;
        }
        /// <summary>
        /// 更新进度条的值
        /// </summary>
        /// <param name="info">进度条信息</param>
        private static void UpdateProgress(ProgressInfo info)
        {
            //如果进度差大于0.01%则跟新（1f主要是为了计算结果为double类型的数据）
            if (Math.Abs((1f * info.CurrentPos / info.MaxPos) - info.CurrentVal) > 0.0001)
            {
                info.CurrentVal = 1f * info.CurrentPos / info.MaxPos;
                PROGRESS_INFO progressInfo = new PROGRESS_INFO();
                progressInfo.Value = string.Format("进度：{0:0.00 %}", info.CurrentVal);
                progressInfo.Status = string.Format("状态：{0}({1:0.00%})",info.Status,info.CurrentVal);
                SendMessage(PubVal.ProcessHwnd, (int)WM_MSG.WM_MSG_PROCESS_UPDATE, IntPtr.Zero, ref progressInfo);
            }
        }
        /// <summary>
        /// 更新状态
        /// </summary>
        /// <param name="str"></param>
        public static void UpdateStringInfo(string str)
        {
            PROGRESS_INFO progressInfo = new PROGRESS_INFO();
            progressInfo.Status = "状态："+str;
            SendMessage(PubVal.ProcessHwnd, (int)WM_MSG.WM_MSG_PROCESS_UPDATE, IntPtr.Zero, ref progressInfo);
        }
        /// <summary>
        /// 关闭进度条窗口
        /// 处理数据完成后需要关闭进度条
        /// </summary>
        public static  void CloseProcessFrm()
        {
            SendMessage(PubVal.ProcessHwnd, (int)WM_MSG.WM_MSG_PROCESS_CLOSE_FRM, IntPtr.Zero, IntPtr.Zero);
        }
        /// <summary>
        /// 运行一个过程
        /// </summary>
        /// <param name="start">过程名称</param>
        public static void StartThread(ThreadStart start)
        {
            ShowProgressFrm(start);
        }
        public static void StartNormalThread(ThreadStart start)
        {
            Thread Thd = new Thread(start);
            Thd.Start();
        }
        public static void StartNormalThread(ParameterizedThreadStart start, object parameter)
        {
            Thread Thd = new Thread(start);
            Thd.Start(parameter);
        }
        /// <summary>
        /// 运行一个带参数的过程
        /// </summary>
        /// <param name="start">过程名称</param>
        /// <param name="parameter">参数</param>
        public static void StartThread(ParameterizedThreadStart start,object parameter)
        {
            ShowProgressFrm(start, parameter);
        }
        /// <summary>
        /// 显示进度条
        /// </summary>
        private static void ShowProgressFrm(ThreadStart start)
        {
            Progress Frm = new Progress(start);
            Frm.ShowDialog();
        }
        /// <summary>
        /// 显示进度条窗口
        /// </summary>
        private static void ShowProgressFrm(ParameterizedThreadStart start,object parameter)
        {
            Progress Frm = new Progress(start,parameter);
            Frm.ShowDialog();
        }
        /// <summary>
        /// 延时
        /// </summary>
        /// <param name="nimiSec"></param>
        public static void Delay(int nimiSec)
        {
            Thread.Sleep(nimiSec);
        }
    }
}
